-module(oma).

-export([parse_header/1]).


%%
%% API
%%

parse_header(File) ->
    case file:open(File, [read, binary, raw]) of
        {ok, S} ->
            {ok, Header} = file:pread(S, 0, 16#0c60),
            H = case read_header(Header) of
                error ->
                    {error, invalid_header};
                Data ->
                    Data
            end,
            file:close(S),
            H;
        _ ->
            {error, file_cannot_be_opened}
    end.

%%
%% Internal functions
%%


read_header(<<$e, $a, $3, Rest/binary>>) ->
    Data = decode_header(Rest, []),
    Data;

read_header(_) ->
    error.

% Title
decode_header(<<$T, $I, $T, $2, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        TitleLength = Var - 2,
        <<Title:TitleLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{title, Title}]);

% Artist
decode_header(<<$T, $P, $E, $1, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        ArtistLength = Var - 2,
        <<Artist:ArtistLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{artist, Artist}]);

% Album
decode_header(<<$T, $A, $L, $B, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        AlbumLength = Var - 2,
        <<Album:AlbumLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{album, Album}]);

% Genre
decode_header(<<$T, $C, $O, $N, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        GenreLength = Var - 2,
        <<Genre:GenreLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{genre, Genre}]);

% Track number
decode_header(<<$T, $X, $X, $X, _:8/binary,
      $O, 0, $M, 0, $G, 0, 95, 0, $T, 0, $R, 0, $A, 0, $C, 0, $K, 0,
      0, 0,
      Track:1/binary,
      Rest/binary>>, L) ->

      decode_header(Rest, [L|{track, list_to_integer(binary_to_list(Track))}]);

% Year
decode_header(<<$T, $Y, $E, $R, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        YearLength = Var - 2,
        <<Year:YearLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{year, Year}]);

% Length
decode_header(<<$T, $L, $E, $N, _:2/binary,
      Var:2/integer-unit:8, _:4/binary,
      Rest/binary>>, L) ->

        LenLength = Var - 2,
        <<Length:LenLength/binary, Rest2/binary>> = Rest,
        decode_header(Rest2, [L|{length, Length}]);

decode_header(<<$E, $A, $3, $0, 16#60, 16#FF, 16#FF, _Rest/binary>>, L) ->
    L;

decode_header(<<>>, L) ->
    L;

decode_header(Bin, L) ->
    {_, NewBin} = split_binary(Bin, 1),
    decode_header(NewBin, L).